package service

import (
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"go_my_framework/app/core/session"
	"go_my_framework/app/dao"
	"go_my_framework/app/global/request"
	"go_my_framework/app/model"
	"go_my_framework/util/sli"
)

type AdminService struct {
}

// 获取管理员列表
func (a *AdminService) GetAdminList(f request.AdminForm) ([]model.Admin, int64, error) {
	if f.Page == 0 {
		f.Page = 1
	}
	if f.Limit == 0 {
		f.Limit = 10
	}
	data, count, err := dao.NewAdminDaoImpl().GetList(f.Page, f.Limit, f.Username)
	if err != nil {
		return []model.Admin{}, 0, errors.New(err.Error())
	}

	return data, count, nil
}

func (a *AdminService) AddAdmin(username string, realName string, password string, rePassword string, roleId int, mobile string) error {
	if password != rePassword {
		return errors.New("两次密码不一致")
	}
	adminInfo := dao.NewAdminDaoImpl().FindRow(username)
	if adminInfo.Id != 0 {
		return errors.New("已存在同名管理员")
	}
	encPassword := md5.Sum([]byte(password))
	pw := fmt.Sprintf("%x", encPassword) // 二进制转16进制
	return dao.NewAdminDaoImpl().Create(username, pw, roleId, realName, mobile)
}

func (a *AdminService) GetRow(username string) model.Admin {
	return dao.NewAdminDaoImpl().FindRow(username)
}

func (a *AdminService) EditAdmin(id int, username string, password string, rePassword string, roleId int, realName string, mobile string) error {
	if (password != "" || rePassword != "") && password != rePassword {
		return errors.New("两次密码不一致")
	}
	adminInfo := a.GetRow(username)
	if adminInfo.Id != 0 && id != adminInfo.Id {
		return errors.New("已存在同名用户")
	}
	var data model.Admin
	data.Username = username
	data.RoleId = roleId
	data.RealName = realName
	data.Mobile = mobile
	if password != "" {
		data.Password = password
	}
	return dao.NewAdminDaoImpl().Update(id, data)
}

func (a *AdminService) DelAdmin(id int) error {
	return dao.NewAdminDaoImpl().Del(id)
}

func (a *AdminService)Privilege(roleId int, purviewId []int) error {
	// 现有权限
	existing, _ := dao.NewRolePurviewDaoImpl().GetPurviewListByRoleId(roleId)
	// TODO 这里要优化调用公共函数
	//existPurviewId := sli.ArrayColumn(existing, "AdminPurviewId")
	var existPurviewId = make([]int, len(existing), len(existing))
	for _, v := range existing {
		existPurviewId = append(existPurviewId, v.AdminPurviewId)
	}

	// 取差集
	if len(existPurviewId) > 0 {
		var del []int
		for _, v := range existPurviewId {
			if !sli.InArray(v, purviewId) {
				del = append(del, v)
			}
		}
		// 没有再次勾选的要删掉
		err := dao.NewRolePurviewDaoImpl().DelPurview(roleId, del)
		if err != nil {
			return err
		}
	}

	// 新勾选的要增加
	var data []model.RolePurview
	for _, val := range purviewId {
		var tmp = model.RolePurview{
			AdminRoleId:    roleId,
			AdminPurviewId: val,
		}
		data = append(data, tmp)
	}
	return dao.NewRolePurviewDaoImpl().CreateMulti(data)
}

func (a *AdminService) SignIn(c *gin.Context, username string, password string) error {
	encPass := md5.Sum([]byte(password)) // md5
	code := fmt.Sprintf("%x", encPass) // 二进制转16进制

	// 查询
	adminInfo := dao.NewAdminDaoImpl().FindRow(username)
	if adminInfo.Id == 0 || adminInfo.Password != code {
		return errors.New("账号或密码错误")
	}

	// 权限
	rolePurview, _ := dao.NewRolePurviewDaoImpl().GetPurviewListByRoleId(adminInfo.RoleId)
	purviewIds := make([]int, len(rolePurview), len(rolePurview))
	for k, v := range rolePurview {
		purviewIds[k] = v.AdminPurviewId
	}

	// 用户信息存session
	err := saveAdminToSession(c, adminInfo, purviewIds)
	if err != nil {
		return err
	}

	return nil
}

func saveAdminToSession(c *gin.Context, adminInfo model.Admin, purviewIds []int) error {
	_ = session.Set(c, "admin_id", adminInfo.Id)
	_ = session.Set(c, "role_id", adminInfo.RoleId)
	_ = session.Set(c, "real_name", adminInfo.RealName)
	_ = session.Set(c, "username", adminInfo.Username)
	_ = session.Set(c, "purview_ids", purviewIds)
	return nil
}

func (a *AdminService) IsSignedIn(c *gin.Context,) bool {
	if session.Get(c, "admin_id") == nil {
		return false
	} else {
		return true
	}
}

func (a *AdminService) GetAdminSession(c *gin.Context) (int, int, string, string, []int) {
	id := session.Get(c, "admin_id").(int)
	roleId := session.Get(c, "role_id").(int)
	username := session.Get(c, "username").(string)
	realName := session.Get(c, "real_name").(string)
	purviewIds := session.Get(c, "purview_ids").([]int)
	return id, roleId, username, realName, purviewIds
}

func (a *AdminService) ClearAdminSession(c *gin.Context) error {
	_ = session.Del(c, "admin_id")
	_ = session.Del(c, "role_id")
	_ = session.Del(c, "real_name")
	_ = session.Del(c, "username")
	_ = session.Del(c, "purview_ids")
	return nil
}

func (a *AdminService) GetAdminMap() map[int]model.Admin {
	var adminMap = make(map[int]model.Admin)
	admin := dao.NewAdminDaoImpl().GetAllAdmin()
	if len(admin) == 0 {
		return adminMap
	}
	for _, v := range admin {
		adminMap[v.Id] = v
	}
	return adminMap
}